# -*- coding:utf-8 -*-
# @Time : 2022/1/13 下午4:02 
# @Author : zdy
# @File : UIMultiPointCalibration.py
# desc:

from Class.GraphBase import GraphBase
from Class.Format import *
from Class.CSConfig import MultiPointCalibrationItem
from Class.VoltSignal import dataBase, VoltSignal
from Class.Factor import Factor
import pyqtgraph as pg
from Class.Devices import *

import datetime, copy, os
from importQT import *

class Paras(object):
    def __init__(self, result, standard):
        self.result = result
        self.standard = standard


class UIMultiPointCalibration(QDialog, Ui_MultiPointCalibration):
    def __init__(self):
        super(UIMultiPointCalibration, self).__init__()
        self.setupUi(self)
        self.setWindowTitle('多点校正')
        self.applyResource()
        self.multiPointItems = [[] for i in range(0, dataBase.maxChannel)]
        self.inittwData()
        self.initGraph()
        self.setAcceptDrops(True)
        self.btnCalculation.clicked.connect(self.btnCalculation_clicked)
        self.btnDelete.clicked.connect(self.btnDelete_clicked)
        self.btnNew.clicked.connect(self.btnNew_clicked)
        self.btnSave.clicked.connect(self.btnSave_clicked)
        self.btnReset.clicked.connect(self.btnReset_clicked)

        self.xItems =[]
        self.yItems=[]

        for i in range(0, dataBase.maxChannel):
            if hasattr(device.config, "multiPointItems") and len(device.config.multiPointItems[i]) > 0:
                self.multiPointItems[i] = copy.deepcopy(device.config.multiPointItems[i])
        self.rbtn0.setText(E1)
        self.rbtn1.setText(E2)
        self.rbtn2.setText(E3)
        self.rbtn3.setText(E4)
        self.rbtn0.toggled.connect(self.switchChannel)
        self.rbtn1.toggled.connect(self.switchChannel)
        self.rbtn2.toggled.connect(self.switchChannel)
        self.rbtn3.toggled.connect(self.switchChannel)
        self.currentChannel = 0
        self.rbtn0.setChecked(1)

    def applyResource(self):
        self.setWindowIcon(getIcon())

    def switchChannel(self, isChecked):
        if isChecked:
            if self.sender() == self.rbtn0:
                self.currentChannel = 0
            if self.sender() == self.rbtn1:
                self.currentChannel = 1
            if self.sender() == self.rbtn2:
                self.currentChannel = 2
            if self.sender() == self.rbtn3:
                self.currentChannel = 3
            self.initParas()

    def initParas(self):
        self.xItems = copy.deepcopy(device.config.factors[self.currentChannel].xItem)
        self.yItems = copy.deepcopy(device.config.factors[self.currentChannel].yItem)
        if hasattr(device.config, "multiPointItems"):
            self.multiPointItems[self.currentChannel] = copy.deepcopy(device.config.multiPointItems[self.currentChannel])
        self.bingDatas()
        self.setParams()

    def initGraph(self):
        self.graphBase = GraphBase(self)
        self.graph = self.graphBase.graphwiget
        self.graph.setLabel("left", "标准值%")
        self.graph.setLabel("bottom", "结果%")
        self.gridLayout.addWidget(self.graph)
        self.curve = []

    def bingDatas(self):
        count = self.twData.rowCount()
        for i in range(count - 1, -1, -1):
            self.twData.removeRow(i)
        self.setDatas(self.multiPointItems[self.currentChannel])

    def setParams(self):
        """根据当前参数，更新界面参数显示，绘制曲线图"""
        ptx = []
        pty = []
        for item in self.multiPointItems[self.currentChannel]:
            if item.include:
                ptx.append(item.result)
                pty.append(item.standard)
            item.calculated = Factor.CalculateResultByMulti(item.result, self.xItems,self.yItems,False)
        for i in self.curve:
            i.clear()
            self.graph.removeItem(i)
        self.curve.clear()

        # while len(self.graph.getPlotItem().items) >1:
        #     del self.graph.getPlotItem().items[len(self.graph.getPlotItem().items)-1]
        #
        # self.graph.getPlotItem().curves.clear()
        # self.graph.getPlotItem().dataItems.clear()
        # self.graph.getPlotItem().vb.clear()
        if len(ptx) > 0:
            self.curve.append(self.graph.plot(x=ptx, y=pty, pen=pg.mkPen(color="w", width=2), symbol='o'))
            self.curve.append(self.graph.plot(x = self.xItems, y=self.yItems, pen=pg.mkPen(color="r", width=2), style=Qt.DashLine))
        self.updateTWFromList()

    def inittwData(self):
        self.twData.setColumnCount(7)
        # 设置表头粗体
        self.twData.setHorizontalHeaderLabels(['日期', '样品名称', '序号', '标准值%', '重新计算后结果%', '结果%(不含多点校正)', '包含'])
        font = self.twData.horizontalHeader().font()
        font.setBold(True)
        self.twData.horizontalHeader().setFont(font)
        # self.twData.setSelectionBehavior(QAbstractItemView.SelectRows)  # 整行选中的方式
        self.twData.setItemDelegate(DelegateResult(self, [3, 4, 5], None, None, [3,5], False,None))  # 结果小数位数
        self.twData.horizontalHeader().setStretchLastSection(True)  # 最后一列填充
        self.twData.setColumnWidth(0, 200)
        self.twData.setColumnWidth(4, 200)
        self.twData.setColumnWidth(5, 200)
        # self.twData.verticalHeader().setVisible(False)  # 行首不可见
        self.twData.horizontalHeader().setSectionsClickable(False)  # 表头不可点击
        self.twData.cellChanged.connect(self.twData_cellChanged)

    def twData_cellChanged(self, row, column):
        value = self.twData.item(row,column).data(0)
        ranges = self.twData.selectedRanges()
        count = len(ranges)
        rows = []
        for i in range(count):
            for j in range(ranges[i].topRow(), ranges[i].bottomRow() + 1):
                rows.append(j)
        self.twData.blockSignals(True)
        for i in rows:
            self.twData.item(i, column).setData(0,value)
        self.twData.blockSignals(False)

    def setData(self, data: MultiPointCalibrationItem):
        '''
        向twData里添加一行数据
        :param data: MultiPointCalibrationItem
        :return:
        '''
        row = self.twData.rowCount()
        self.twData.insertRow(row)
        alignment = int(Qt.AlignHCenter | Qt.AlignVCenter)
        for i in range(7):
            item = QTableWidgetItem()
            if i == 0:
                item.setData(Qt.DisplayRole, data.id)
            elif i == 1:
                item.setData(Qt.DisplayRole, data.name)
            elif i == 2:
                item.setData(Qt.DisplayRole, data.num)
            elif i == 3:
                item.setData(Qt.DisplayRole, data.standard)
            elif i == 4:
                item.setData(Qt.DisplayRole, data.calculated)
            elif i == 5:
                item.setData(Qt.DisplayRole, data.result)
            elif i == 6:
                item = QTableWidgetItem(data.include)
                item.setCheckState(Qt.Checked if data.include else Qt.Unchecked)
            if i not in [3,5]:
                item.setFlags(item.flags() & (~Qt.ItemIsEditable))
            item.setTextAlignment(alignment)
            self.twData.setItem(row, i, item)
        self.twData.setShowGrid(True)  # 有数据时才起作用

    def setDatas(self, items):
        '''
        向twData里添加多行数据
        :param items:   MultiPointCalibrationItem
        :return:
        '''
        self.twData.blockSignals(True)
        for data in items:
            self.setData(data)
        self.twData.blockSignals(False)

    def btnNew_clicked(self):
        item = MultiPointCalibrationItem()
        item.id = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        item.input = True
        self.setDatas([item])
        self.multiPointItems[self.currentChannel].append(item)

    def btnDelete_clicked(self):
        ranges = self.twData.selectedRanges()
        count = len(ranges)
        row = []
        for i in range(0, count):
            for j in range(ranges[i].topRow(), ranges[i].bottomRow() + 1):
                row.append(j)
        row.sort(key=int, reverse=True)  # 因为删除一行后，后面的行号都会变化，所以用sort方法将list进行降序排列
        self.twData.blockSignals(True)
        for i in row:
            self.twData.removeRow(i)
            self.multiPointItems[self.currentChannel].pop(i)
        self.twData.blockSignals(False)

    def btnCalculation_clicked(self):
        if self.currentChannel == -1:
            return
        if bool(1 - self.updateListFromTW()):
            return
        if len(self.multiPointItems[self.currentChannel]) > 0:
            standards = []
            for item in self.multiPointItems[self.currentChannel]:
                if item.input:
                    # 根据输入的校正后的值，反算获得不使用多点校正计算出的结果
                    if item.result <=0:
                        pass
                        # item.result = Factor.CalculateResultByMulti(item.calculated,
                        #                                             device.config.factors[self.currentChannel].xItem,
                        #                                             device.config.factors[self.currentChannel].yItem,
                        #                                             True)
                else:
                    vs = VoltSignal.loadAll(item.id)
                    if vs == None:
                        QMessageBox.warning(self, "提示", "找不到数据")
                        return
                    item.weight = vs.sampleWeight
                    item.blank = vs.factors[self.currentChannel].blank
                    item.flux = vs.fluxWeight
                    item.calculated = device.config.factors[self.currentChannel]. \
                        calculateResult(vs.listT, vs.listData[self.currentChannel], vs.sampleWeight,
                                        vs.average[self.currentChannel], vs.fluxWeight)
                    # 存放不含
                    item.result = Factor.CalculateResultByMulti(item.calculated,
                                                                device.config.factors[self.currentChannel].xItem,
                                                                device.config.factors[self.currentChannel].yItem,
                                                                True)
                if item.include:  # 添加所有勾选的项，包括手动输入的
                    standards.append(Paras(result=item.result, standard=item.standard))

            # 排序，计算均值点
            standards.sort(key=lambda x: x.result)
            standardCurrent = standards[0].standard;
            results = []
            self.xItems.clear()
            self.yItems.clear()
            for i, s in enumerate(standards):
                if s.standard == standardCurrent:
                    results.append(s.result)
                if s.standard != standardCurrent or i == len(standards) - 1:
                    if len(results) > 0:
                        self.xItems.append(Factor.calculateAverage(results))
                        self.yItems.append(standardCurrent)
                        results.clear()
                    if s.standard != standardCurrent and i == len(standards) - 1:
                        self.xItems.append(s.result)
                        self.yItems.append(s.standard)
                    results.append(s.result)
                    standardCurrent = s.standard
            # if self.yItems[0] != 0:
            #     self.yItems.insert(0, 0.0)
            #     self.xItems.insert(0, 0.0)
            self.setParams()

    def updateListFromTW(self):
        """根据校正表更新Items中的标准值和包含
        :return 是否更新成功
        """
        rowcount = self.twData.rowCount()
        if rowcount > 0:
            for i in range(0, rowcount):
                id = self.twData.item(i, 0).text()
                items = list(filter(lambda x: x.id == id, self.multiPointItems[self.currentChannel]))
                if len(items) == 1:
                    try:
                        items[0].standard = float(self.twData.item(i, 3).text())
                        items[0].include = self.twData.item(i, 6).checkState() == Qt.Checked
                        items[0].result = float(self.twData.item(i, 5).text())
                        items[0].calculated = float(self.twData.item(i, 4).text())
                    except Exception as ex:
                        QMessageBox.warning(self, "多点校正", "数据异常")
                        return False
        return True

    def updateTWFromList(self):
        """根据baseItems更新校正表中的计算后"""
        self.twData.blockSignals(True)
        rowcount = self.twData.rowCount()
        if rowcount > 0:
            for i in range(rowcount):
                id = self.twData.item(i, 0).text()
                items = list(filter(lambda x: x.id == id, self.multiPointItems[self.currentChannel]))
                if len(items) == 1:
                    try:
                        if not items[0].input:
                            self.twData.item(i, 4).setData(Qt.DisplayRole, items[0].calculated)
                        self.twData.item(i, 5).setData(Qt.DisplayRole, items[0].result)
                    except Exception as ex:
                        QMessageBox.warning(self,"多点校正","数据异常")
                        break
        self.twData.blockSignals(False)
        return True


    def btnSave_clicked(self):
        device.config.factors[self.currentChannel].xItem = self.xItems
        device.config.factors[self.currentChannel].yItem = self.yItems
        device.config.multiPointItems[self.currentChannel] =copy.deepcopy(self.multiPointItems[self.currentChannel])

    def btnReset_clicked(self):
        device.config.factors[self.currentChannel].xItem.clear()
        device.config.factors[self.currentChannel].yItem.clear()
        device.config.multiPointItems[self.currentChannel].clear()
        self.initParas()

    def dropEvent(self, a0: QDropEvent) -> None:
        """当拖拽操作在目标控件上被释放时，触发"""
        if a0.mimeData().hasText():
            dropstr = a0.mimeData().text()
            # print(dropstr)
            rowindexsstr = dropstr.split("&")
            rowIndexs = []
            for i in rowindexsstr:
                rowIndexs.append(int(i))
            count = len(rowIndexs)
            if count > 0:
                results = device.modelResult.getMultiPointItems(rowIndexs)
                if len(results) > 0:
                    self.setDatas(results)
                    for i in results:
                        self.multiPointItems[self.currentChannel].append(i)
        pass

    def dragEnterEvent(self, a0: QDragEnterEvent) -> None:
        """拖拽操作时，进入该控件时，触发该事件，"""
        if a0.mimeData().hasText():
            a0.setAccepted(True)
            # print("准备接收drag")
        else:
            a0.setAccepted(False)
            # print("drag不匹配")
        pass